package com.leinao.media.utils;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import cn.hutool.system.OsInfo;
import cn.hutool.system.SystemUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.leinao.media.constants.MediaConstant;
import com.leinao.media.entity.Camera;
import com.leinao.media.entity.TemperatureRule;
import com.leinao.media.exception.MediaException;
import com.leinao.media.sdk.dh.lib.NetSDKLib;
import com.leinao.media.sdk.hk.HCNetSDK;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.List;

/**
 * 流媒体相关操作工具类
 *
 * @author zhangyu
 * @date 2021/11/26 17:36
 */
public class MediaUtil {

    private static final Log log = LogFactory.get();

    /**
     * 获取lib文件路径
     *
     * @param type 1：海康netSdk 2：大华netSdk 3:大华configSdk
     * @return lib文件路径
     */
    public static String getLibPath(int type) {
        // 海康netSdk,Windows路径
        String hkNetWindowsPath = "C:\\sdk\\hk\\HCNetSDK.dll";
        // 海康netSdk,Linux路径
        String hkNetLinuxPath = "/leinao/sdk/hk/libhcnetsdk.so";

        // 大华netSdk,Windows路径
        String dhNetWindowsPath = "C:\\sdk\\dh\\dhnetsdk.dll";
//        大华configSdk, Windows路径
        String dhConfWindowsPath = "C:\\sdk\\dh\\dhconfigsdk.dll";

        // 大华netSdk,Linux路径
        String dhNetLinuxPath = "/leinao/sdk/dh/libdhnetsdk.so";
        // 大华configSdk,Linux路径`
        String dhConfigLinuxPath = "/leinao/sdk/dh/libdhconfigsdk.so";

        OsInfo osInfo = SystemUtil.getOsInfo();
        // Windows
        if (osInfo.isWindows()) {
            switch (type) {
                case 1:
                    return hkNetWindowsPath;
                case 2:
                    return dhNetWindowsPath;
                case 3:
                    return dhConfWindowsPath;
                default:
                    throw new MediaException("类型传入错误");
            }
        }
        // Linux
        if (osInfo.isLinux()) {
            switch (type) {
                case 1:
                    return hkNetLinuxPath;
                case 2:
                    return dhNetLinuxPath;
                case 3:
                    return dhConfigLinuxPath;
                default:
                    throw new MediaException("类型传入错误");
            }
        }
        return "";
    }

    /**
     * sdk 初始化
     */
    public static void init(int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_ALL:
                HkUtil.init();
                DhUtil.init();
                break;
            case MediaConstant.NVR_TYPE_HK:
                HkUtil.init();
                break;
            case MediaConstant.NVR_TYPE_DH:
                DhUtil.init();
                break;
            default:
                throw new MediaException("错误类型!");
        }
    }

    /**
     * 激活设备
     *
     * @param ip       IP
     * @param port     端口号
     * @param password 初始密码
     * @param type     设备类型
     */
    public static String activateDevice(String ip, String port, String password, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.activateDevice(ip, port, password);
            case MediaConstant.NVR_TYPE_DH:
                // 大华没有激活的概念，这里先不管了
                log.info("设备：{}，激活成功", ip);
                return "";
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 设备注册
     *
     * @param ip       IP
     * @param port     端口
     * @param userName 用户名
     * @param password 密码
     * @param type     设备类型
     * @return 用户ID
     */
    public static long login(String ip, String port, String userName, String password, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.login(ip, port, userName, password);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.login(ip, port, userName, password);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 判断设备状态
     *
     * @param uid  用户ID
     * @param type 设备类型
     */
    public static String getDeviceStatus(long uid, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getDeviceStatus(uid);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getDeviceStatus(uid);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 销毁当前登录信息
     *
     * @param uid  用户ID
     * @param type 设备类型
     */
    public static void logout(long uid, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                HkUtil.logout(uid);
                break;
            case MediaConstant.NVR_TYPE_DH:
                DhUtil.logout(uid);
                break;
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 释放SDK资源
     */
    public static void cleanup(int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_ALL:
                HkUtil.cleanup();
                DhUtil.cleanup();
                break;
            case MediaConstant.NVR_TYPE_HK:
                HkUtil.cleanup();
                break;
            case MediaConstant.NVR_TYPE_DH:
                DhUtil.cleanup();
                break;
            default:
//                throw new MediaException("错误类型!");
        }
    }

    /**
     * 获取DVR下面的摄像机列表
     *
     * @param ip       设备ip
     * @param uid      用户ID
     * @param userName 用户名
     * @param password 密码
     * @param type     设备类型
     * @return 摄像机列表
     */
    public static List<Camera> getCameraList(String ip, long uid, String userName, String password, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getCameraList(ip, uid, userName, password);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getCameraList(ip, uid, userName, password);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 云台控制
     *
     * @param type         设备类型
     * @param uid          用户ID
     * @param iChannel     通道号
     * @param dwPTZCommand 云台控制命令
     * @param dwStop       是否停止 0：开启，1：停止
     * @param speed        云台控制的速度，用户按不同解码器的速度控制值设置。取值范围[1,7]
     * @return boolean
     */
    public static String cloudPlatformControl(int type, long uid, Integer iChannel, Integer dwPTZCommand, Integer dwStop, Integer speed) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.cloudPlatformControl(uid, iChannel, dwPTZCommand, dwStop, speed);
            case MediaConstant.NVR_TYPE_DH:
                // 命令转换
                if (dwPTZCommand == HCNetSDK.TILT_UP) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_UP_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.TILT_DOWN) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_DOWN_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.PAN_LEFT) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_LEFT_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.PAN_RIGHT) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_RIGHT_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.UP_LEFT) {
                    dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_LEFTTOP;
                }
                if (dwPTZCommand == HCNetSDK.UP_RIGHT) {
                    dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RIGHTTOP;
                }
                if (dwPTZCommand == HCNetSDK.DOWN_LEFT) {
                    dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_LEFTDOWN;
                }
                if (dwPTZCommand == HCNetSDK.DOWN_RIGHT) {
                    dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RIGHTDOWN;
                }
                if (dwPTZCommand == HCNetSDK.ZOOM_IN) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_ZOOM_ADD_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.ZOOM_OUT) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_ZOOM_DEC_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.FOCUS_NEAR) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_FOCUS_ADD_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.FOCUS_FAR) {
                    dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_FOCUS_DEC_CONTROL;
                }
                if (dwPTZCommand == HCNetSDK.PAN_AUTO) {
                    dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_STARTPANCRUISE;
                }
                return DhUtil.cloudPlatformControl(uid, iChannel, dwPTZCommand, dwStop, speed);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 设置预置位
     *
     * @param uid            用户ID
     * @param iChannel       通道号
     * @param dwPTZPresetCmd 操作云台预置点命令
     * @param dwPresetIndex  预置点的序号（从1开始），最多支持300个预置点
     * @param type           设备类型
     * @return boolean
     */
    public static boolean setPresetLocation(long uid, Integer iChannel, Integer dwPTZPresetCmd, Integer dwPresetIndex, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.setPresetLocation(uid, iChannel, dwPTZPresetCmd, dwPresetIndex);
            case MediaConstant.NVR_TYPE_DH:
                // 命令转换
                if (dwPTZPresetCmd == 8) {
                    dwPTZPresetCmd = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_POINT_SET_CONTROL;
                }
                if (dwPTZPresetCmd == 9) {
                    dwPTZPresetCmd = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_POINT_DEL_CONTROL;
                }
                if (dwPTZPresetCmd == 39) {
                    dwPTZPresetCmd = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_POINT_MOVE_CONTROL;
                }
                return DhUtil.setPresetLocation(uid, iChannel, dwPTZPresetCmd, dwPresetIndex);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 获取设备硬盘信息
     *
     * @param uid  登录句柄
     * @param type 设备类型
     * @return JSONObject
     */
    public static JSONObject getDeviceDiskInfo(long uid, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getDeviceDiskInfo(uid);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getDeviceDiskInfo(uid);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 获取录像总时长
     *
     * @param uid  用户句柄
     * @param type 设备类型
     * @return 录像总时长
     */
    public static long getSumVideoTime(String ip, long uid, String userName, String password, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getSumVideoTime(ip, uid, userName, password);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getSumVideoTime(ip, uid, userName, password);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 录像起止时间查询
     *
     * @param uid     用户ID
     * @param channel 通道号
     * @return JSONObject
     */
    public static JSONObject searchVideoTime(long uid, Integer channel) {
        return HkUtil.searchVideoTime(uid, channel);
    }

    /**
     * 录像月历查询
     *
     * @param uid     用户ID
     * @param channel 通道号
     * @param year    年
     * @param month   月
     * @param type    设备类型
     */
    public static JSONArray getVideoMonth(long uid, int channel, int year, int month, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getVideoMonth(uid, channel, year, month);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getVideoMonth(uid, channel, year, month);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 录像回放码流地址获取
     *
     * @param ip        DVR的IP
     * @param userName  用户名
     * @param passWord  密码
     * @param id        相机ID
     * @param channel   通道号
     * @param startTime 录像开始时间
     * @param endTime   录像结束时间
     * @param type      设备类型
     * @return 录像回放码流地址
     */
    public static String getPlayBackAddress(String ip, String userName, String passWord, String id, String channel,
                                            Date startTime, Date endTime, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getPlayBackAddress(ip, userName, passWord, id, startTime, endTime);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getPlayBackAddress(ip, userName, passWord, channel, startTime, endTime);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 录像文件查询
     *
     * @param uid       用户ID
     * @param channel   通道号
     * @param startTime 录像开始时间
     * @param endTime   录像结束时间
     * @param type      设备类型
     * @return JSONObject
     */
    public static JSONObject findVideoFile(long uid, int channel, Date startTime, Date endTime, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.findVideoFile(uid, channel, startTime, endTime);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.queryRecordFile(uid, channel, startTime, endTime);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 抓取图片
     *
     * @param uid         用户ID
     * @param channel     通道号
     * @param saveAddress 保存地址
     * @param quality     画质（可选）
     * @param type        设备类型
     */
    public static String captureJpeg(long uid, int channel, String saveAddress, Integer quality, Integer type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.captureJpeg(uid, channel, saveAddress, quality);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.captureJpeg(uid, channel, saveAddress, quality);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 开始录像
     *
     * @param uid     用户ID
     * @param channel 通道号
     * @param type    设备类型
     * @return 视频预览返回值
     */
    public static long startMakeVideo(long uid, int channel, String saveAddress, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.startMakeVideo(uid, channel, saveAddress);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.startMakeVideo(uid, channel, saveAddress);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 停止录像
     *
     * @param lPreviewHandle 实时预览返回值
     */
    public static void stopMakeVideo(long lPreviewHandle, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                HkUtil.stopMakeVideo(lPreviewHandle);
                break;
            case MediaConstant.NVR_TYPE_DH:
                DhUtil.stopMakeVideo(lPreviewHandle);
                break;
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 录像文件下载(按时间)
     *
     * @param uid         用户ID
     * @param channel     通道号
     * @param startTime   开始时间
     * @param endTime     结束时间
     * @param saveAddress 保存地址
     * @param type        设备类型
     */
    public static long downloadVideoFileByTime(long uid, int channel, String fileName, Date startTime,
                                               Date endTime, String saveAddress, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.downloadVideoFileByTime((int) uid, channel, fileName, startTime, endTime, saveAddress);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.downloadVideoFileByTime(uid, channel, fileName, startTime, endTime, saveAddress);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 通过文件名下载
     *
     * @param uid         用户ID
     * @param fileName    文件名
     * @param saveAddress 保存地址
     */
    @Deprecated
    public static void downloadVideoFileByFileName(int uid, String fileName, String saveAddress) {
        HkUtil.downloadVideoFileByFileName(uid, fileName, saveAddress);
    }

    /**
     * 获取下载进度
     *
     * @param iDownHandle 下载句柄
     * @param type        设备类型
     * @return 下载进度
     */
    public static int getDownLoadProgress(long iDownHandle, int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                return HkUtil.getDownLoadProgress(iDownHandle);
            case MediaConstant.NVR_TYPE_DH:
                return DhUtil.getDownLoadProgress(iDownHandle);
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 停止下载
     */
    public static void stopDownloadVideoFile(int type) {
        switch (type) {
            case MediaConstant.NVR_TYPE_HK:
                HkUtil.stopDownloadVideoFile();
                break;
            case MediaConstant.NVR_TYPE_DH:
                DhUtil.stopAllDownLoadRecordFile();
                break;
            default:
                throw new MediaException("错误的设备类型!");
        }
    }

    /**
     * 测温规则
     *
     * @param param 测温规则参数
     * @throws UnsupportedEncodingException Exception
     */
    public static boolean makeTemperatureRule(TemperatureRule param) {
        return HkUtil.makeTemperatureRule(param);
    }

    /**
     * 设置布防
     *
     * @param ip  设备ip
     * @param uid 用户ID
     */
    public static int setUpAlarm(long uid, String ip, HCNetSDK.FMSGCallBack_V31 callBackV31) {
        return HkUtil.setUpAlarm(ip, uid, callBackV31);
    }

    /**
     * 报警撤防
     *
     * @param alarmHandle 报警布防句柄
     */
    public static boolean closeAlarmChan(int alarmHandle) {
        return HkUtil.closeAlarmChan(alarmHandle);
    }

    /**
     * 开启实时测温
     *
     * @param ip  设备ip
     * @param uid 用户ID
     */
    public static int setUpThermometry(String ip, long uid, HCNetSDK.FRemoteConfigCallback realTimeThermometryCallBack) {
        return HkUtil.setUpThermometry(ip, uid, realTimeThermometryCallBack);
    }

    /**
     * 关闭实时测温
     *
     * @param alarmHandle 报警布防句柄
     */
    public static boolean closeThermometry(int alarmHandle) {
        return HkUtil.closeThermometry(alarmHandle);
    }

}
